/***************************************************************************************************************************************
 * Copyright (C) 2001-2012 LearnLift USA																	*
 * Contact: Learnlift USA, 12 Greenway Plaza, Suite 1510, Houston, Texas 77046, support@memorylifter.com					*
 *																								*
 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License	*
 * as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.			*
 *																								*
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty	*
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.	*
 *																								*
 * You should have received a copy of the GNU Lesser General Public License along with this library; if not,					*
 * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA					*
 ***************************************************************************************************************************************/
// The following code was generated by Microsoft Visual Studio 2005.
// The generateQuestionThread owner should check each generateQuestionThread for validity.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Text;
using System.Collections.Generic;
using MLifter.BusinessLayer;
using MLifterTest.BusinessLayer;
using MLifter.DAL.Interfaces;
using System.Diagnostics;
using MLifter.DAL;
using MLifterTest.DAL;
using System.IO;
using MLifter.Generics;
using System.Threading;
namespace MLifterTest.BusinessLayer
{
    /// <summary>
    ///This is a generateQuestionThread class for MLifter.BusinessLayer.LearnLogic and is intended
    ///to contain all MLifter.BusinessLayer.LearnLogic Unit Tests
    ///</summary>
    [TestClass()]
    public class LearnLogicTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the generateQuestionThread context which provides
        ///information about and functionality for the current generateQuestionThread run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }
        #region Additional generateQuestionThread attributes
        //// 
        ////You can use the following additional attributes as you write your tests:
        ////
        ////Use ClassInitialize to run code before running the first generateQuestionThread in the class
        ////
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //    DictionaryTest.MyClassInitialize(testContext);
        //}
        ////
        ////Use ClassCleanup to run code after all tests in a class have run
        ////
        [ClassCleanup()]
        public static void MyClassCleanup()
        {
            TestInfrastructure.MyClassCleanup();
        }
        //
        //Use TestInitialize to run code before running each generateQuestionThread
        //
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each generateQuestionThread has run
        //
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        private static Random random
        {
            get { return DictionaryTest.Random; }
        }

        private static bool GetRandBool()
        {
            return DictionaryTest.GetRandBool();
        }

        /// <summary>
        /// Test the de-/promotion of a card.
        /// </summary>
        /// <remarks>Documented by Dev05, 2008-09-09</remarks>
        [TestMethod]
        [TestProperty("BL", "ChrFin"), DataSource("TestSources")]
        public void GradeCardTest()
        {
            if (TestInfrastructure.IsActive(TestContext))
            {
                ConnectionStringStruct connectionString = TestInfrastructure.GetConnectionStringWithDummyData(TestContext);
                LearnLogic llogic = new LearnLogic(OpenUserProfileTests.GetUserAdmin, (DataAccessErrorDelegate)delegate { return; });
                //llogic.User.Authenticate((GetLoginInformation)MLifterTest.DAL.TestInfrastructure.GetTestUser,
                //    connectionString, (DataAccessErrorDelegate)delegate { return; });

                try
                {
                    llogic.OpenLearningModule(new LearningModulesIndexEntry(connectionString));
                }
                catch (IsOdxFormatException)
                {
                    if (TestInfrastructure.ConnectionType(TestContext) == "File")
                        return;
                    else
                        throw;
                }

                llogic.OnLearningModuleOptionsChanged();

                Card card = llogic.Dictionary.Cards.GetCardByID(llogic.CurrentCardID);
                int oldBox = card.BaseCard.Box = 5;

                UserInputSubmitEventArgs e = new UserInputSubmitTextEventArgs(0, card.CurrentAnswer.Words.Count, card.CurrentAnswer.Words.Count, true, card.CurrentAnswer.Words.ToString());
                llogic.OnUserInputSubmit(this, e);

                Assert.AreEqual<int>(oldBox + 1, card.BaseCard.Box, "Card was not correctly promoted!");

                card.BaseCard.Box = oldBox;

                e = new UserInputSubmitTextEventArgs(5, 0, 5, false, string.Empty);
                llogic.OnUserInputSubmit(this, e);

                Assert.AreEqual<int>(1, card.BaseCard.Box, "Card was not demoted!");
            }
        }

        /// <summary>
        /// Tests if the learn logic selects the correct learning mode based in the card content.
        /// </summary>
        /// <remarks>Documented by Dev03, 2008-09-12</remarks>
        [TestMethod]
        [TestProperty("BL", "AleAbe"), DataSource("TestSources")]
        public void LearnLogicLearnModeTest()
        {
            if (TestInfrastructure.IsActive(TestContext))
            {
                ConnectionStringStruct connectionString = TestInfrastructure.GetConnectionStringWithDummyData(TestContext);
                LearnLogic learnLogic = new LearnLogic(OpenUserProfileTests.GetUserAdmin, (DataAccessErrorDelegate)delegate { return; });
                //learnLogic.User.Authenticate(OpenUserProfileTests.GetUserAdmin, connectionString, (DataAccessErrorDelegate)delegate { return; });
                try
                {
                    learnLogic.OpenLearningModule(new LearningModulesIndexEntry(connectionString));
                }
                catch (IsOdxFormatException)
                {
                    if (TestInfrastructure.ConnectionType(TestContext) == "File")     //success
                        return;
                    else
                        throw;
                }

                learnLogic.User.Dictionary.Settings.QueryTypes.ImageRecognition = true;
                learnLogic.User.Dictionary.Settings.QueryTypes.ListeningComprehension = true;
                learnLogic.User.Dictionary.Settings.QueryTypes.Sentence = true;
                for (int i = 0; i < TestInfrastructure.LoopCount; i++)
                {
                    learnLogic.OnLearningModuleOptionsChanged();
                    Card card = learnLogic.User.Dictionary.Cards.GetCardByID(learnLogic.CurrentCardID);
                    switch (learnLogic.User.Dictionary.LearnMode)
                    {
                        case LearnModes.ImageRecognition:
                            Assert.IsTrue(card.ContainsImage(Side.Question.ToString()), "Card must contain image for ImageRecognition mode.");
                            break;
                        case LearnModes.ListeningComprehension:
                            Assert.IsTrue(card.ContainsAudio(Side.Question.ToString()), "Card must contain audio for ListeningComprehension mode.");
                            break;
                        case LearnModes.Sentence:
                            Assert.IsTrue(card.CurrentQuestionExample.Words.Count > 0, "Card must contain example for Sentence mode.");
                            break;
                        default:
                            continue;
                    }
                }
            }
        }

        /// <summary>
        /// Tests the doubles login.
        /// </summary>
        /// <remarks>Documented by Dev05, 2008-11-24</remarks>
        [TestMethod]
        [TestProperty("BL/DAL", "ChrFin"), DataSource("TestSources")]
        [ExpectedException(typeof(DoubleLoginException), "The supposed Error 'DoubleLoginException' hasn't occurred!")]
        public void DoubleLoginTest()
        {
            if (TestInfrastructure.IsActive(TestContext))
            {
                switch (TestInfrastructure.ConnectionType(TestContext))
                {
                    case "File":
                    case "sqlce":
                        throw new DoubleLoginException();
                    default:
                        break;
                }

                ConnectionStringStruct connectionString = TestInfrastructure.GetConnectionString(TestContext);
                LearnLogic learnLogic = new LearnLogic(OpenUserProfileTests.GetUserAdmin, (DataAccessErrorDelegate)delegate { return; });
                learnLogic.User.Authenticate((GetLoginInformation)MLifterTest.DAL.TestInfrastructure.GetTestUser,
                    connectionString, (DataAccessErrorDelegate)delegate { return; });

                //Doesn't throw the Exception because the UserFactory logs out the previous user
                LearnLogic lLogic = new LearnLogic(OpenUserProfileTests.GetUserAdmin, (DataAccessErrorDelegate)delegate { return; });
                lLogic.User.Authenticate((GetLoginInformation)GetLoginErrorMethod, connectionString, (DataAccessErrorDelegate)delegate { return; });

                //Check instead if old user is logged out properly
                if (!learnLogic.UserSessionAlive)
                    throw new DoubleLoginException();
            }
            else
            {
                throw new DoubleLoginException();
            }
        }
        private static bool userSubmitted = false;
        private UserStruct? GetLoginErrorMethod(UserStruct u, ConnectionStringStruct c)
        {
            if (!userSubmitted)
            {
                userSubmitted = true;
                UserStruct user = MLifterTest.DAL.TestInfrastructure.GetTestUser(u, c).Value;
                user.CloseOpenSessions = false;
                return user;
            }

            LoginError err = u.LastLoginError;

            if (err == LoginError.AlreadyLoggedIn)
                throw new DoubleLoginException();
            else
                throw new Exception("The supposed Error 'AlreadyLoggedIn' hasn't occurred!");
        }
        private class DoubleLoginException : Exception { };

        /// <summary>
        /// Tests for exception thrown when opening null argument.
        /// </summary>
        /// <remarks>Documented by Dev09, 2009-03-05</remarks>
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void OpenLearningModuleNullTest()
        {
            LearnLogic llogic = new LearnLogic((GetLoginInformation)MLifterTest.DAL.TestInfrastructure.GetTestUser, (DataAccessErrorDelegate)delegate { return; });
            llogic.OpenLearningModule(null);
        }

        /// <summary>
        /// Tests for exception thrown when opening a file that does not exist.
        /// </summary>
        /// <remarks>Documented by Dev09, 2009-03-05</remarks>
        [TestMethod]
        [ExpectedException(typeof(FileNotFoundException))]
        public void OpenLearningModuleFileNotFoundTest()
        {
            LearnLogic llogic = new LearnLogic((GetLoginInformation)MLifterTest.DAL.TestInfrastructure.GetTestUser, (DataAccessErrorDelegate)delegate { return; });
            LearningModulesIndexEntry module = new LearningModulesIndexEntry();
            module.ConnectionString = new ConnectionStringStruct(DatabaseType.Xml, "invalid");
            llogic.OpenLearningModule(module);
        }

        /// <summary>
        /// Runs a test for opening file types that throw exceptions.
        /// </summary>
        /// <param name="ext">The ext.</param>
        /// <remarks>Documented by Dev09, 2009-03-05</remarks>
        private void FileExtTestHelper(String ext)
        {
            // create temp file with desired extension
            String filename = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + "." + ext);
            File.Create(filename);

            LearnLogic llogic = new LearnLogic((GetLoginInformation)MLifterTest.DAL.TestInfrastructure.GetTestUser, (DataAccessErrorDelegate)delegate { return; });
            LearningModulesIndexEntry module = new LearningModulesIndexEntry();
            module.ConnectionString = new ConnectionStringStruct(DatabaseType.Xml, filename);
            llogic.OpenLearningModule(module);
        }

        /// <summary>
        /// Tests exception thrown for trying to open *.dip files.
        /// </summary>
        /// <remarks>Documented by Dev09, 2009-03-05</remarks>
        [TestMethod]
        [ExpectedException(typeof(DipNotSupportedException))]
        public void OpenLearningModuleFileExtDipTest()
        {
            FileExtTestHelper("dip");
        }

        /// <summary>
        /// Tests exception thrown for trying to open *.zip files.
        /// </summary>
        /// <remarks>Documented by Dev09, 2009-03-05</remarks>
        [TestMethod]
        [ExpectedException(typeof(NeedToUnPackException))]
        public void OpenLearningModuleFileExtZipTest()
        {
            FileExtTestHelper("zip");
        }

        /// <summary>
        /// Tests exception thrown for trying to open *.dzp files.
        /// </summary>
        /// <remarks>Documented by Dev09, 2009-03-05</remarks>
        [TestMethod]
        [ExpectedException(typeof(NeedToUnPackException))]
        public void OpenLearningModuleFileExtDzpTest()
        {
            FileExtTestHelper("dzp");
        }

        /// <summary>
        /// Tests exception thrown for trying to open *.odf files.
        /// </summary>
        /// <remarks>Documented by Dev09, 2009-03-05</remarks>
        [TestMethod]
        [ExpectedException(typeof(IsOdfFormatException))]
        public void OpenLearningModuleFileExtOdfTest()
        {
            FileExtTestHelper("odf");
        }

        /// <summary>
        /// Tests exception thrown for trying to open *.odx files.
        /// </summary>
        /// <remarks>Documented by Dev09, 2009-03-05</remarks>
        [TestMethod]
        [ExpectedException(typeof(IsOdxFormatException))]
        public void OpenLearningModuleFileExtOdxTest()
        {
            FileExtTestHelper("odx");
        }

        /// <summary>
        /// Tests exception thrown for trying to open files with a different extension than expected.
        /// </summary>
        /// <remarks>Documented by Dev09, 2009-03-05</remarks>
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void OpenLearningModuleFileExtOtherTest()
        {
            FileExtTestHelper("txt");
        }

        /// <summary>
        /// Tests trying to close an open module to open another, when closing fails.
        /// </summary>
        /// <remarks>Documented by Dev09, 2009-03-05</remarks>
        [TestMethod]
        [TestProperty("BL/DAL", "ChrFin"), DataSource("TestSources")]
        [ExpectedException(typeof(CouldNotCloseLearningModuleException))]
        public void OpenLearningModuleCannotCloseTest()
        {
            if (TestInfrastructure.IsActive(TestContext) && TestInfrastructure.ConnectionType(TestContext).ToLower() != "file")
            {
                LearnLogic llogic = new LearnLogic((GetLoginInformation)MLifterTest.DAL.TestInfrastructure.GetTestUser, (DataAccessErrorDelegate)delegate { return; });
                LearningModulesIndexEntry module = new LearningModulesIndexEntry();
                module.ConnectionString = TestInfrastructure.GetConnectionStringWithDummyData(TestContext);

                llogic.LearningModuleClosing += new LearnLogic.LearningModuleClosingEventHandler(llogic_LearningModuleClosing);
                llogic.OpenLearningModule(module);
                llogic.OpenLearningModule(module);
            }
            else
                throw new CouldNotCloseLearningModuleException();
        }

        /// <summary>
        /// Override LearningModuleClosing event to force it to fail.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="MLifter.BusinessLayer.LearningModuleClosingEventArgs"/> instance containing the event data.</param>
        /// <remarks>Documented by Dev09, 2009-03-05</remarks>
        void llogic_LearningModuleClosing(object sender, LearningModuleClosingEventArgs e)
        {
            e.Cancel = true;
        }
    }
}
